from common.contrib import admin
from .models import *
from .forms import *
from django.db import transaction
from import_export.formats import base_formats
from tuntun.settings import DJANGO_REPO_USER_GROUP_NAME, DJANGO_SUPER_USER_GROUP_NAME, DJANGO_NO_RECHARGE_USER_GROUP_NAME, DJANGO_PRODUCT_MGR_USER_GROUP_NAME
from django.db.models import Q

# Register your models here.
import datetime
import time
from django.http import HttpResponse
from django.contrib import messages
from apps.mix.tasks import task_pre_sale_publish
from django.utils.html import format_html
from import_export.admin import ExportMixin
from import_export.resources import ModelResource
from import_export.fields import Field


def make_file_upload_html(field_id, href_url, input_value):
    return format_html(
        """
        <input type="file" id="%s--file-input" />
        <a id="%s--upload-button" class="ub">上传</a>
        <div class="progress" style="display:inline">
            <div style="display:inline" id="%s--progress-bar" 
                class="progress-bar" 
                role="progressbar" 
                aria-valuenow="0" 
                aria-valuemin="0" 
                aria-valuemax="100" 
                style="min-width: 2em;">
                0%%
            </div>
        </div>
        <a target=_blank id="%s--preview-link" href=%s>%s</a>""" % (field_id, field_id, field_id, field_id,  href_url, "预览", )
    )


class IndexBannerAdmin(admin.ModelAdmin):
    form = IndexBannerForm
    list_display = ('link',)

    def save_model(self, request, obj, form, change):
        value = request.POST.get('banner_public_file_id', '')
        if value.split('//')[0] in ['http:', 'https:']:
            obj.banner_public_file_id = self.related_aliyun_oss_file(request.POST.get('banner_public_file_id'))
        obj.save()

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        form.base_fields['banner_public_file_id'].help_text = make_file_upload_html('banner_public_file_id', obj.image_url if obj else '', obj.image_url if obj else '')
        return form


admin.site.register(IndexBanner, IndexBannerAdmin)


class StoreAdmin(admin.ModelAdmin):
    form = StoreForm
    list_display = ['name', 'store_type', 'video_banner_public_file_id', 'banner_file_ids']

    def save_model(self, request, obj, form, change):
        file_fields = ['video_banner_public_file_id', ]
        for ff in file_fields:
            value = getattr(obj, ff)
            if value.startswith('http:') or value.startswith('https:'):
                pf_id = self.related_aliyun_oss_file(value)
                setattr(obj, ff, pf_id)
        for i in range(5):
            file_key = 'banner_id%d' % i
            value = request.POST.get(file_key)
            if value.startswith('http:') or value.startswith('https:'):
                pf_id = self.related_aliyun_oss_file(value)
                bb, _ = StoreBanner.objects.get_or_create(store=obj, order=i)
                bb.banner_public_file_id = pf_id
                bb.save()
        obj.save()

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        form.base_fields['name'].initial = obj.name if obj else ''
        form.base_fields['video_banner_public_file_id'].help_text = make_file_upload_html("video_banner_public_file_id", obj.video if obj else '', obj.video if obj else '')
        for i in range(5):
            form.base_fields['banner_id%d' % i].help_text = make_file_upload_html('banner_id%d' % i, obj.get_banner_url(i) if obj else '', obj.get_banner_url(i) if obj else '')
            form.base_fields['banner_id%d' % i].initial = obj.get_banner_id(i) if obj else ''
        return form


admin.site.register(Store, StoreAdmin)


class BrandAdmin(admin.ModelAdmin):
    form = BrandForm
    list_display = ['name', 'store', 'no']

    def get_readonly_fields(self, request, obj=None):
        if obj is None:
            return []
        else:
            return ['no', ]

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        form.base_fields['name'].initial = obj.name if obj else ''
        form.base_fields['logo_public_file_id'].help_text = make_file_upload_html("logo_public_file_id", obj.logo if obj else '', obj.logo if obj else '')
        form.base_fields['video_banner_public_file_id'].help_text = make_file_upload_html("video_banner_public_file_id", obj.video if obj else '', obj.video if obj else '')
        for i in range(5):
            form.base_fields['banner_id%d' % i].help_text = make_file_upload_html('banner_id%d' % i, obj.get_banner_url(i) if obj else '', obj.get_banner_url(i) if obj else '')
            form.base_fields['banner_id%d' % i].initial = obj.get_banner_id(i) if obj else ''
        return form

    def save_model(self, request, obj, form, change):
        if not change:
            obj.attention_account = 0
        file_fields = ['logo_public_file_id', 'video_banner_public_file_id', ]
        for ff in file_fields:
            value = getattr(obj, ff)
            if value.startswith('http:') or value.startswith('https:'):
                pf_id = self.related_aliyun_oss_file(value)
                setattr(obj, ff, pf_id)
        for i in range(5):
            file_key = 'banner_id%d' % i
            value = request.POST.get(file_key)
            if value.startswith('http:') or value.startswith('https:'):
                pf_id = self.related_aliyun_oss_file(value)
                bb, _ = BrandLongImage.objects.get_or_create(brand=obj, order=i)
                bb.banner_public_file_id = pf_id
                bb.save()
        obj.save()


admin.site.register(Brand, BrandAdmin)


class ProductAdmin(admin.ModelAdmin):
    form = ProductForm
    list_display = ['name', 'brand', 'tea_type', 'no', 'stock', 'status', 'get_make_gb_unique_bar_codes_link', 'init_store_unit_status', 'init_store_unit_result', 'get_set_avg_price_link', 'in_repo_count', 'publish_count', 'pre_sale_start_time', 'pre_sale_end_time', 'free_repo_cost',]

    def get_readonly_fields(self, request, obj=None):
        if request.user.groups.all().filter(Q(name=DJANGO_SUPER_USER_GROUP_NAME)|Q(name=DJANGO_PRODUCT_MGR_USER_GROUP_NAME)):
            if obj is None:
                return []
            else:
                if GoodsBlock.objects.filter(product_id=obj.id):
                    return ['tea_type', 'no', 'age_code', 'tea_cake_type']
                else:
                    return []
        else:
            return [f.name for f in self.model._meta.fields]

    def get_fields(self, request, obj=None):
        if request.user.groups.all().filter(name=DJANGO_SUPER_USER_GROUP_NAME):
            fields = super().get_fields(request, obj)
        elif request.user.groups.all().filter(name=DJANGO_PRODUCT_MGR_USER_GROUP_NAME):
            fields = super().get_fields(request, obj)
        else:
            fields = ['name', 'publish_count']
        return fields

    def get_list_display(self, request):
        fields = list(super().get_list_display(request))
        if request.user.groups.all().filter(name=DJANGO_SUPER_USER_GROUP_NAME):
            fields += ['get_set_avg_price_link',]
        return fields

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        form.base_fields['logo_public_file_id'].help_text = make_file_upload_html("logo_public_file_id", obj.logo if obj else '', obj.logo if obj else '')
        form.base_fields['video_banner_public_file_id'].help_text = make_file_upload_html("video_banner_public_file_id", obj.video if obj else '', obj.video if obj else '')
        for i in range(5):
            form.base_fields['banner_id%d' % i].help_text = make_file_upload_html('banner_id%d' % i, obj.get_banner_url(i) if obj else '', obj.get_banner_url(i) if obj else '')

        return form

    def has_delete_permission(self, request, obj=None):
        return True

    def delete_model(self, request, obj):
        super(ProductAdmin, self).delete_model(request, obj)

    def has_add_permission(self, request):
        if request.user.groups.all().filter(name=DJANGO_SUPER_USER_GROUP_NAME):
            return True
        elif request.user.groups.all().filter(name=DJANGO_PRODUCT_MGR_USER_GROUP_NAME):
            return True
        else:
            # return False
            return True

    def save_model(self, request, obj, form, change):
        #['tea_type', 'no', 'age_code', 'tea_cake_type']
        if obj.no is None or obj.age_code is None or len(obj.no) != 3 or len(obj.age_code) != 5:
            return messages.error(request, '编号必须是三位，年份码必须是5位')
        publish_count = form.cleaned_data.get('publish_count')
        pre_sale_price = form.cleaned_data.get('pre_sale_price')
        if not change:
            if Product.objects.filter(no=obj.no, tea_type=obj.tea_type, age_code=obj.age_code):
                return messages.error(request, '产品编号，茶饼类型，年份码不能重复')
            obj.status = Product.ProductStatus.REPO_IN_ING.name
            obj.max_price = pre_sale_price
            obj.avg_price = pre_sale_price
            obj.last_trade_price = pre_sale_price
            obj.up_down_percent = Decimal('0.00')
            obj.save()
        else:
            if Product.objects.filter(~Q(id=obj.pk), no=obj.no, tea_type=obj.tea_type, age_code=obj.age_code):
                return messages.error(request, '产品编号，茶饼类型，年份码不能和其他产品重复')
            obj.save()
            if obj.status == Product.ProductStatus.PRE_SALE_ING.name or obj.status == Product.ProductStatus.REPO_ENTERED.name:
                if obj.publish_count != obj.in_repo_count():
                    obj.status = Product.ProductStatus.REPO_IN_ING.name
                    obj.save()
                    return messages.error(request, '已入库数量和发行数量不一样，无法处理')
                if obj.in_repo_count() == 0:
                    obj.status = Product.ProductStatus.REPO_IN_ING.name
                    obj.save()
                    return messages.error(request, '入库数量为0，无法处理')
                if obj.status == Product.ProductStatus.PRE_SALE_ING.name:
                    # 触发异步任务
                    task_pre_sale_publish.delay(obj.id)
        # Logo
        file_fields = ['logo_public_file_id', 'video_banner_public_file_id', ]
        for ff in file_fields:
            value = getattr(obj, ff)
            if value.startswith('http:') or value.startswith('https:'):
                pf_id = self.related_aliyun_oss_file(value)
                setattr(obj, ff, pf_id)
        for i in range(5):
            file_key = 'banner_id%d' % i
            value = request.POST.get(file_key)
            if value.startswith('http:') or value.startswith('https:'):
                pf_id = self.related_aliyun_oss_file(value)
                bb, _ = ProductLongImage.objects.get_or_create(product=obj, order=i)
                bb.banner_public_file_id = pf_id
                bb.save()
        packages = form.cleaned_data['packages']
        if packages:
            obj.package_ids = packages
            for pid in packages:
                pkg = Package.objects.get(pk=pid)
                if type(pkg.product_ids) != list:
                    pkg.product_ids = []
                if obj.id not in pkg.product_ids:
                    pkg.product_ids.append(obj.id)
                    pkg.save()
            other_packages = Package.objects.filter().exclude(id__in=packages)
            for other_package in other_packages:
                if type(other_package.product_ids) != list:
                    other_package.product_ids = []
                if obj.id in other_package.product_ids:
                    other_package.product_ids.remove(obj.id)
                    other_package.save()
        obj.save()


admin.site.register(Product, ProductAdmin)


class PackageAdmin(admin.ModelAdmin):
    form = PackageForm
    list_display = ('name', 'price', 'avatar_public_file_id')

    def save_model(self, request, obj, form, change):
        # Logo
        avatar_public_file_id = self.put_file_to_aliyun_oss(request.FILES.get('avatar_public_file_id', None))
        if avatar_public_file_id is not None:
            file = PublicFile.objects.get(pk=avatar_public_file_id)
            if file.meta_data['size'] > 500000:
                return messages.error(request, '上传文件超限（500K)')
            obj.avatar_public_file_id = avatar_public_file_id
        obj.save()

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        if obj:
            print(form.base_fields.keys())
            form.base_fields['avatar_public_file_id'].help_text = format_html('<a target=_blank href=%s>%s</a>' % (obj.avatar, obj.avatar))
        return form

    def has_add_permission(self, request):
        if request.user.groups.all().filter(name=DJANGO_SUPER_USER_GROUP_NAME):
            return True
        else:
            return False

    def has_delete_permission(self, request, obj=None):
        if request.user.groups.all().filter(name=DJANGO_SUPER_USER_GROUP_NAME):
            return True
        else:
            return False


admin.site.register(Package, PackageAdmin)


class GoodsBlockAdmin(ExportMixin, admin.ModelAdmin):
    form = GoodsBlockForm
    list_display = ['product', 'unique_code', 'store_unit_repo_no', 'no', 'owner_user', 'locked_by_user', 'locked_expire_at_dt_format', 'is_out_repo_display']
    # readonly_fields = ['unique_code', ]
    search_fields = ('unique_code',)
    list_filter = ('trade_type', 'product', )

    def get_readonly_fields(self, request, obj=None):
        if obj:
            return ['unique_code',]
        return []

    def get_export_resource_class(self):
        class GoodsBlockResource(ModelResource):
            product = Field()
            class Meta:
                model = GoodsBlock
                fields = ('unique_code',)
            store_unit_repo_no = Field()
            def dehydrate_product(self, goods_block):
                return goods_block.product.name
            def dehydrate_store_unit_repo_no(self, goods_block):
                return StoreUnitThree.objects.get(pk=goods_block.store_unit_id).repo_no
        return GoodsBlockResource

    def get_export_formats(self):
        return [base_formats.CSV, ]

    def save_model(self, request, obj, form, change):
        from apps.repo.models import StoreUnitThree
        gb_data = form.cleaned_data['gb']
        product = gb_data['product']
        repo = Repo.objects.first()
        if change:
            return messages.error(request, '区块信息无法修改')
        else:
            if GoodsBlock.objects.filter(unique_code=gb_data['unique_code']).first():
                return messages.error(request, '唯一码已录入过')
            if GoodsBlock.objects.filter(product=product).count() == product.publish_count:
                return messages.error(request, '入库已完成（发行数量和入库数量已经一致）')
            with transaction.atomic():
                # 处理存储单元
                # 先找已存在的空闲
                store_spec = StoreUnitThree.StoreSpec.get_key_name_by_product_tea_cake_type(product.tea_cake_type)
                valid_repo_store_areas = StoreUnitThree.StoreSpec.get_valid_repo_store_areas(store_spec)
                valid_repo_indexs = StoreUnitThree.get_valid_repo_indexs()

                su = StoreUnitThree.objects.filter(in_use=False, store_spec=store_spec, repo=repo, repo_store_area__in=valid_repo_store_areas).order_by('repo_no').first()
                if not su:
                    su_info = None
                    for valid_repo_index in valid_repo_indexs:
                        for valid_repo_store_area in valid_repo_store_areas:
                            last_su = StoreUnitThree.objects.filter(store_spec=store_spec, repo=repo, repo_index=valid_repo_index, repo_store_area=valid_repo_store_area).order_by('-repo_no').first()
                            su_info = StoreUnitThree.get_next_store_unit_info(last_su, valid_repo_index, valid_repo_store_area, repo.pk)
                            if su_info:
                                break
                        if su_info:
                            break
                    if su_info:
                        su = StoreUnitThree.objects.create(**su_info)

                gb_data.update({
                    "repo_id": su.repo.pk,
                    "store_unit_id": su.pk,
                    "trade_price": gb_data['product'].pre_sale_price,
                    "avg_price": gb_data['product'].pre_sale_price,
                    'trade_datetime': datetime.datetime.now(),
                })
                gb = GoodsBlock.objects.create(**gb_data)
                su.in_use = True
                su.save()
                # 入库节点
                gbc = GoodsBlockChain(
                    goods_block=gb,
                    operator_user_id=None,
                    chain_type=GoodsBlockChain.ChainType.IN_REPO.name,
                    node_datetime=datetime.datetime.now(),
                    storage_repo_id=su.repo.pk,
                    storage_repo_days=0
                )
                gbc_op = gbc.get_block_chain_node_outputs()
                gbc.title = gbc_op['title']
                gbc.contents = gbc_op['contents']
                gbc.repo_info = gbc_op['repo_info']
                gbc.save()
admin.site.register(GoodsBlock, GoodsBlockAdmin)


class IndexBannerAdmin(admin.ModelAdmin):
    fields = ['banner_public_file_id', 'link']
# admin.site.register(IndexBanner, IndexBannerAdmin)

class ProductLongImageAdmin(admin.ModelAdmin):
    fields = ['product', 'banner_public_file_id', 'order']
    list_display = ['product', 'order']
# admin.site.register(ProductLongImage, ProductLongImageAdmin)


class MarketOrderAdmin(admin.ModelAdmin):
    list_display = ('user', 'product', 'intention_type',
                    'publish_type', 'offered_price', 'count',
                    'direct_to_user', 'as_gift', 'buy_in_market_order',
                    'related_order', 'related_order_status', 'get_add_time', 'status')
# admin.site.register(MarketOrder, MarketOrderAdmin)


class GoodsBlockChainAdmin(admin.ModelAdmin):
    list_display = ('goods_block_id', 'chain_type')
    list_filter = ('goods_block',)
    # ordering = ('-goods_block_id',)
# admin.site.register(GoodsBlockChain, GoodsBlockChainAdmin)


class ProductAvgPriceAdmin(admin.ModelAdmin):
    list_display = ('product', 'avg_price', 'get_add_time')
admin.site.register(ProductAvgPrice, ProductAvgPriceAdmin)
